refactor(e2e): add bounded polling primitives for live readiness checks - #6367
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Enterprise Run ID: 📒 Files selected for processing (3)
🚧 Files skipped from review as they are similar to previous changes (3)
📝 WalkthroughWalkthroughAdds a generic bounded polling utility for e2e tests, migrates two live polling loops to use it, and adds a deterministic test suite covering the polling behavior. ChangesBounded polling primitive
Estimated code review effort: 3 (Moderate) | ~25 minutes Suggested labels: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (6)
test/e2e/fixtures/polling.ts (2)
47-58: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick winDelay is executed even on the attempt that will immediately exceed the bound and fail.
When the final unsuccessful probe still has a positive
delay,pollUntilsleeps before the next loop iteration discoversattempt > options.attempts(or the deadline has passed) and breaks — wasting a full delay cycle right before throwing. This adds real time to failing test runs (e.g.PROBE_DELAY_MSdefaults to 5s inconcurrent-gateway-ports.test.ts, and the deterministic test at Line 37 ofe2e-polling.test.tsalso captures this: delays[10, 20]include the delay after the last, doomed attempt).♻️ Skip the trailing delay when no further attempt will run
if (options.accept(value, attempt)) return lastAttempt; + const hasNextAttempt = + (options.attempts === undefined || attempt + 1 <= options.attempts) && + (deadline === undefined || now() < deadline); + if (!hasNextAttempt) break; const delay = typeof options.delayMs === "function" ? options.delayMs(attempt) : (options.delayMs ?? 0); if (delay > 0) await sleep(delay);🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@test/e2e/fixtures/polling.ts` around lines 47 - 58, In pollUntil, the delay is applied after the last probe even when the next loop would immediately stop because options.attempts or the deadline has been exceeded. Update the control flow around the attempt loop in test/e2e/fixtures/polling.ts so the code checks whether another attempt can still run before calling sleep, using the existing pollUntil, options.attempts, deadline, and delay logic to skip the trailing delay on a doomed final attempt.
45-46: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winAbort signal isn't checked while a probe or sleep is in flight.
options.signal?.abortedis only checked at the top of the loop, so calling.abort()mid-sleep(delay)(or mid-probe) won't cancel until the current wait/probe completes — up to a fulldelayMsof extra latency.♻️ Race sleep against the abort signal
- if (delay > 0) await sleep(delay); + if (delay > 0) { + await Promise.race([ + sleep(delay), + new Promise<void>((resolve) => options.signal?.addEventListener("abort", () => resolve(), { once: true })), + ]); + }Also applies to: 55-57
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@test/e2e/fixtures/polling.ts` around lines 45 - 46, The polling loop in the `polling` helper only checks `options.signal?.aborted` at the top of `for (let attempt = 1; ; attempt += 1)`, so aborts during `sleep(delay)` or an in-flight probe are delayed until the next iteration. Update the `polling` logic to race both the probe and the delay against `options.signal` (or otherwise short-circuit immediately on abort), and make the same change in the later abort-sensitive section referenced by the `PollingError` flow so `abort()` cancels promptly at any point in the wait cycle.test/e2e/support/e2e-polling.test.ts (2)
19-39: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick winTest locks in an unnecessary sleep after the final permitted attempt before reporting exhaustion.
Tracing
pollUntil: withattempts: 2anddelayMs: (attempt) => attempt * 10, the loop sleeps after attempt 2 fails (delays === [10, 20]) even though attempt 2 is the last one allowed — the extra 20ms delay is pure waste before the function throws. This test correctly documents current behavior, but the behavior itself means every migrated call site (e.g.,waitForSandboxReadywithPROBE_DELAY_MSdefaulting to 5s) incurs one extra full delay on every readiness timeout before the failure is surfaced. Consider havingpollUntilskip the trailing sleep when the attempt about to be incremented would exceedattempts/deadlineMs.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@test/e2e/support/e2e-polling.test.ts` around lines 19 - 39, The pollUntil behavior currently sleeps after the final allowed attempt before throwing PollingError, which adds an unnecessary trailing delay. Update pollUntil so the backoff sleep only happens when another probe will still run, using the attempts/deadline checks before calling sleep. Keep the existing exhaustion reporting and lastAttempt capture intact, and adjust the e2e polling test around pollUntil to assert no extra sleep occurs on the final failed attempt.
41-75: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winDeadline and terminal sub-tests are solid; abort coverage only exercises the pre-aborted case.
The abort assertion (Lines 64-74) only verifies behavior when the signal is already aborted before
pollUntilis called. It doesn't exercise abort happening mid-poll (e.g., aborting insideprobeafter the first attempt), which is the more interesting path through the per-iterationsignal?.abortedcheck. Consider adding a case where the signal is aborted between attempts to guard against future regressions in that check's placement.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@test/e2e/support/e2e-polling.test.ts` around lines 41 - 75, The abort coverage in pollUntil only checks a signal that is already aborted before the call, so it misses the per-iteration abort path. Add a test case in the e2e-polling suite that uses AbortController with polling.abort happening during execution (for example, abort inside or immediately after the first probe call) and assert that pollUntil rejects with the expected abort message. Keep the existing deadline and terminal checks, and extend the abort coverage around pollUntil, probe, and the signal-based loop handling.Source: Path instructions
test/e2e/live/concurrent-gateway-ports.test.ts (1)
171-178: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winFragile string-match to distinguish terminal vs. exhaustion errors.
error.message.includes("terminal phase")couples this catch block to the exact wording produced by theterminalcallback above (Line 167). If that message text is ever reworded, a genuine terminal-phase failure would silently fall through to the generic "did not reach Ready/Running" branch, losing the terminal diagnosis without any compile-time signal.Since
error.lastAttempt?.valuealready carries the parsedphase, recompute the terminal condition directly instead of parsing the message string.♻️ Proposed fix: check phase directly instead of message text
} catch (error) { if (!(error instanceof PollingError)) throw error; - if (error.message.includes("terminal phase")) throw error; const last = error.lastAttempt?.value; + const isTerminalPhase = + last?.phase === "Error" || last?.phase === "Failed" || last?.phase === "CrashLoopBackOff"; + if (isTerminalPhase) throw error; throw new Error( `${sandboxName} did not reach Ready/Running on ${gatewayName}; last phase '${last?.phase ?? "missing"}'\n${last?.output ?? ""}`, ); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@test/e2e/live/concurrent-gateway-ports.test.ts` around lines 171 - 178, The catch block in concurrent-gateway-ports.test.ts is using a fragile message substring check to detect terminal-phase polling failures. Update the logic around the PollingError handling so it determines terminal status from the available attempt data instead of error.message text, ideally by inspecting error.lastAttempt?.value.phase in the same branch that currently uses last and the Ready/Running failure message. Keep the terminal-path rethrow behavior, but make it independent of the wording produced by the PollingError terminal callback.test/e2e/live/network-policy-denied-log.ts (1)
35-46: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
delayMs: 1is a magic value repurposed to trigger the injectedsleep/settlehook.
pollUntilonly invokessleepwhendelay > 0(perpolling.ts), sodelayMs: 1here isn't a real delay duration — it exists solely to forceoptions.settle()to run between probes. If a future edit "simplifies" this todelayMs: 0(a more natural-looking value),settle()would silently stop being called between attempts, likely reintroducing flaky reads of not-yet-propagated logs. Worth a short comment or a named constant to make the intent explicit.📝 Suggested clarifying comment
const result = await pollUntil({ artifactPrefix: "network-policy-denied-log", attempts: options.attempts, - delayMs: 1, + // Any positive value triggers `sleep` below between attempts; the actual + // wait is delegated to `options.settle()`, not this duration. + delayMs: 1, sleep: async () => options.settle(),🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@test/e2e/live/network-policy-denied-log.ts` around lines 35 - 46, The current pollUntil call uses delayMs: 1 only to force the injected sleep/settle hook to run between probes, not to create a real wait. Keep the nonzero delay in network-policy-denied-log.ts and make that intent explicit by introducing a named constant or short explanatory comment near pollUntil, so future edits to deniedReasonLogProof/options.settle do not “optimize” it to 0 and skip settle().
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@test/e2e/fixtures/polling.ts`:
- Around line 23-30: `PollingError` currently only carries a free-text message,
so terminal, aborted, and exhausted polling failures can only be distinguished
by fragile message parsing. Add a structured discriminator on `PollingError`
(for example a `reason` field) in the class in `test/e2e/fixtures/polling.ts`,
and set it at each throw site in the polling helpers that currently create this
error. Update downstream consumers such as the concurrent-gateway-ports test to
branch on `error.reason` instead of checking `error.message.includes(...)`, so
terminal failures are classified reliably.
---
Nitpick comments:
In `@test/e2e/fixtures/polling.ts`:
- Around line 47-58: In pollUntil, the delay is applied after the last probe
even when the next loop would immediately stop because options.attempts or the
deadline has been exceeded. Update the control flow around the attempt loop in
test/e2e/fixtures/polling.ts so the code checks whether another attempt can
still run before calling sleep, using the existing pollUntil, options.attempts,
deadline, and delay logic to skip the trailing delay on a doomed final attempt.
- Around line 45-46: The polling loop in the `polling` helper only checks
`options.signal?.aborted` at the top of `for (let attempt = 1; ; attempt += 1)`,
so aborts during `sleep(delay)` or an in-flight probe are delayed until the next
iteration. Update the `polling` logic to race both the probe and the delay
against `options.signal` (or otherwise short-circuit immediately on abort), and
make the same change in the later abort-sensitive section referenced by the
`PollingError` flow so `abort()` cancels promptly at any point in the wait
cycle.
In `@test/e2e/live/concurrent-gateway-ports.test.ts`:
- Around line 171-178: The catch block in concurrent-gateway-ports.test.ts is
using a fragile message substring check to detect terminal-phase polling
failures. Update the logic around the PollingError handling so it determines
terminal status from the available attempt data instead of error.message text,
ideally by inspecting error.lastAttempt?.value.phase in the same branch that
currently uses last and the Ready/Running failure message. Keep the
terminal-path rethrow behavior, but make it independent of the wording produced
by the PollingError terminal callback.
In `@test/e2e/live/network-policy-denied-log.ts`:
- Around line 35-46: The current pollUntil call uses delayMs: 1 only to force
the injected sleep/settle hook to run between probes, not to create a real wait.
Keep the nonzero delay in network-policy-denied-log.ts and make that intent
explicit by introducing a named constant or short explanatory comment near
pollUntil, so future edits to deniedReasonLogProof/options.settle do not
“optimize” it to 0 and skip settle().
In `@test/e2e/support/e2e-polling.test.ts`:
- Around line 19-39: The pollUntil behavior currently sleeps after the final
allowed attempt before throwing PollingError, which adds an unnecessary trailing
delay. Update pollUntil so the backoff sleep only happens when another probe
will still run, using the attempts/deadline checks before calling sleep. Keep
the existing exhaustion reporting and lastAttempt capture intact, and adjust the
e2e polling test around pollUntil to assert no extra sleep occurs on the final
failed attempt.
- Around line 41-75: The abort coverage in pollUntil only checks a signal that
is already aborted before the call, so it misses the per-iteration abort path.
Add a test case in the e2e-polling suite that uses AbortController with
polling.abort happening during execution (for example, abort inside or
immediately after the first probe call) and assert that pollUntil rejects with
the expected abort message. Keep the existing deadline and terminal checks, and
extend the abort coverage around pollUntil, probe, and the signal-based loop
handling.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: a118b360-b2e1-436a-b116-30d58dd57f0a
📒 Files selected for processing (4)
test/e2e/fixtures/polling.tstest/e2e/live/concurrent-gateway-ports.test.tstest/e2e/live/network-policy-denied-log.tstest/e2e/support/e2e-polling.test.ts
cv
left a comment
There was a problem hiding this comment.
The caller classifies PollingError by matching human-readable message substrings. Message edits can silently change aborted/terminal/exhausted control flow. Add a structured reason/kind to the error, branch on that field, and cover each outcome with tests. The stale growth-budget check should clear after synchronization with current main; rerun all checks after the fix.
017c3fe to
be606d4
Compare
|
Addressed the requested structured polling failure classification in |
cv
left a comment
There was a problem hiding this comment.
Reviewed the current head. The structured PollingError.reason now replaces message-substring control flow, callers distinguish terminal from exhaustion, and tests cover exhausted, terminal, and aborted outcomes. Current-head CI and contributor-compliance gates are green.
<!-- markdownlint-disable MD041 --> ## Summary Adds the pre-tag v0.0.79 release notes entry to `docs/about/release-notes.mdx` so the release plan can be generated after docs merge. The entry summarizes the merged v0.0.79 release train across inference, diagnostics, runtime hardening, policies, onboarding recovery, and release validation. ## Changes - Added the v0.0.79 release notes section with linked follow-up documentation for OpenRouter onboarding, managed vLLM changes, completion and logging, Deep Agents runtime limits, policy updates, onboarding recovery, and release validation. - Source summary: - #6461 -> `docs/about/release-notes.mdx`: Documents OpenRouter onboarding support and links to inference/provider references. - #6271 and #6272 -> `docs/about/release-notes.mdx`: Documents shell completion and structured logging highlights. - #6465, #6539, #6570, and #6528 -> `docs/about/release-notes.mdx`: Documents status route-drift, orphaned sandbox, gateway cleanup, and DGX Spark express-install diagnostics. - #6523, #6551, #6484, #6488, #6324, and #6542 -> `docs/about/release-notes.mdx`: Documents managed vLLM, Qwen3.6 tool parser, compaction, and timeout/readiness improvements. - #6559, #6538, #6560, #6568, #6552, #6567, and #6587 -> `docs/about/release-notes.mdx`: Documents runtime, credential, proxy, PID namespace, TOML, and provider-state hardening. - #6541, #5415, #6246, #6496, and #6573 -> `docs/about/release-notes.mdx`: Documents GitHub policy, Gmail policy, MCP allowlist, WhatsApp, and messaging-variant updates. - #6253, #6572, #6444, #6536, and #5860 -> `docs/about/release-notes.mdx`: Documents onboarding resume and create-step recovery improvements. - #6508, #6527, #5506, #6588, #6446, #6447, #6582, #6296, #6367, #6397, and #6505 -> `docs/about/release-notes.mdx`: Documents docs, release-risk, and E2E validation updates. ## Type of Change - [ ] Code change (feature, bug fix, or refactor) - [ ] Code change with doc updates - [x] Doc only (prose changes, no code sample modifications) - [ ] Doc only (includes code sample changes) ## Quality Gates <!-- Check exactly one tests line and one docs line. Check other lines when applicable. Add every requested justification or approval reference. --> - [ ] Tests added or updated for changed behavior - [ ] Existing tests cover changed behavior — justification: - [x] Tests not applicable — justification: Release-note prose only. - [x] Docs updated for user-facing behavior changes - [ ] Docs not applicable — justification: - [ ] Sensitive paths changed (security, policy, credentials, preflight, onboarding, inference, runner, sandbox, or messaging) - [ ] Sensitive-path review completed or maintainer-approved waiver recorded — reviewer/approval link/justification: - [ ] Non-success, skipped, or missing CI check accepted by maintainer — check name, approval link, and follow-up issue: ## Verification <!-- Check each applicable item only when supported by the requested evidence. Run targeted tests once per relevant change set and rerun after later edits or hook autofixes that can affect the tested behavior. Do not rerun hook-covered checks. --> - [x] PR description includes the DCO sign-off declaration and every commit appears as `Verified` in GitHub - [x] Normal `pre-commit`, `commit-msg`, and `pre-push` hooks passed, or `npm run check:diff` passed when hooks were skipped or unavailable - [x] Targeted behavior tests pass for the current change set, or tests are marked not applicable above — command/result or justification: Tests not applicable, release-note prose only. - [ ] Applicable broad gate passed — `npm test` for broad runtime/test-harness changes; `npm run check` for repo-wide validation/coverage changes — command/result: - [x] Quality Gates section completed with required justifications or waivers - [x] No secrets, API keys, or credentials committed - [ ] `npm run docs` builds without warnings (doc changes only) - [x] Doc pages follow the [style guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md) (doc changes only) - [ ] New doc pages include SPDX header and frontmatter (new pages only) Docs validation note: `npm run docs:check-agent-variants && npm run docs:check-routes && git diff --check` passed. Full `npm run docs` is currently blocked before Fern validation because the pinned `fern-api@5.65.2` package is unavailable from npm (`ETARGET No matching version found`). --- <!-- DCO sign-off is required in this PR description, and every commit must appear as Verified in GitHub. Run: git config user.name && git config user.email --> Signed-off-by: Julie Yaunches <jyaunches@nvidia.com> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Added release notes for v0.0.79 with a new summary of recent improvements, including onboarding and inference options, operator/CLI diagnostics, sandbox recovery hardening, runtime limits, network policy behavior, and release validation updates. * Added updated references and links for the latest release. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
…ks (NVIDIA#6367) ## Summary Add a deterministic bounded-polling primitive for read-only readiness checks and migrate representative sandbox-readiness and denied-log probes. State-mutating installer/onboard/rebuild retries remain explicit. Closes NVIDIA#6347 Parent epic: NVIDIA#6346 ## Changes - Support attempt and deadline bounds, fixed/dynamic delay, abort signals, terminal states, injected timing, and last-result diagnostics. - Standardize attempt-numbered artifact names. - Migrate concurrent-gateway sandbox readiness and denied network-policy log polling. - Add deterministic support tests for success, exhaustion, backoff, deadlines, terminal states, and cancellation. ## Verification - [x] Signed/Verified commit and all hooks passed - [x] `npm run build:cli` - [x] `npm run typecheck:cli` - [x] `npm run lint` - [x] Polling and denied-log support tests: 7 passed - [x] No mutation retries hidden by the generic helper --- Signed-off-by: Julie Yaunches <jyaunches@nvidia.com> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added a shared end-to-end polling helper with retries, attempt/deadline bounds, configurable delays, abort-signal cancellation, and standardized per-attempt artifact naming. * **Bug Fixes** * Refactored live readiness and denied-log polling to use the shared helper, with consistent terminal-state handling and more informative failures that include the last observed outcome. * **Tests** * Added an e2e test suite covering polling success, retry timing, artifact naming, deadline/terminal early termination, and abort cancellation. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
<!-- markdownlint-disable MD041 --> ## Summary Adds the pre-tag v0.0.79 release notes entry to `docs/about/release-notes.mdx` so the release plan can be generated after docs merge. The entry summarizes the merged v0.0.79 release train across inference, diagnostics, runtime hardening, policies, onboarding recovery, and release validation. ## Changes - Added the v0.0.79 release notes section with linked follow-up documentation for OpenRouter onboarding, managed vLLM changes, completion and logging, Deep Agents runtime limits, policy updates, onboarding recovery, and release validation. - Source summary: - NVIDIA#6461 -> `docs/about/release-notes.mdx`: Documents OpenRouter onboarding support and links to inference/provider references. - NVIDIA#6271 and NVIDIA#6272 -> `docs/about/release-notes.mdx`: Documents shell completion and structured logging highlights. - NVIDIA#6465, NVIDIA#6539, NVIDIA#6570, and NVIDIA#6528 -> `docs/about/release-notes.mdx`: Documents status route-drift, orphaned sandbox, gateway cleanup, and DGX Spark express-install diagnostics. - NVIDIA#6523, NVIDIA#6551, NVIDIA#6484, NVIDIA#6488, NVIDIA#6324, and NVIDIA#6542 -> `docs/about/release-notes.mdx`: Documents managed vLLM, Qwen3.6 tool parser, compaction, and timeout/readiness improvements. - NVIDIA#6559, NVIDIA#6538, NVIDIA#6560, NVIDIA#6568, NVIDIA#6552, NVIDIA#6567, and NVIDIA#6587 -> `docs/about/release-notes.mdx`: Documents runtime, credential, proxy, PID namespace, TOML, and provider-state hardening. - NVIDIA#6541, NVIDIA#5415, NVIDIA#6246, NVIDIA#6496, and NVIDIA#6573 -> `docs/about/release-notes.mdx`: Documents GitHub policy, Gmail policy, MCP allowlist, WhatsApp, and messaging-variant updates. - NVIDIA#6253, NVIDIA#6572, NVIDIA#6444, NVIDIA#6536, and NVIDIA#5860 -> `docs/about/release-notes.mdx`: Documents onboarding resume and create-step recovery improvements. - NVIDIA#6508, NVIDIA#6527, NVIDIA#5506, NVIDIA#6588, NVIDIA#6446, NVIDIA#6447, NVIDIA#6582, NVIDIA#6296, NVIDIA#6367, NVIDIA#6397, and NVIDIA#6505 -> `docs/about/release-notes.mdx`: Documents docs, release-risk, and E2E validation updates. ## Type of Change - [ ] Code change (feature, bug fix, or refactor) - [ ] Code change with doc updates - [x] Doc only (prose changes, no code sample modifications) - [ ] Doc only (includes code sample changes) ## Quality Gates <!-- Check exactly one tests line and one docs line. Check other lines when applicable. Add every requested justification or approval reference. --> - [ ] Tests added or updated for changed behavior - [ ] Existing tests cover changed behavior — justification: - [x] Tests not applicable — justification: Release-note prose only. - [x] Docs updated for user-facing behavior changes - [ ] Docs not applicable — justification: - [ ] Sensitive paths changed (security, policy, credentials, preflight, onboarding, inference, runner, sandbox, or messaging) - [ ] Sensitive-path review completed or maintainer-approved waiver recorded — reviewer/approval link/justification: - [ ] Non-success, skipped, or missing CI check accepted by maintainer — check name, approval link, and follow-up issue: ## Verification <!-- Check each applicable item only when supported by the requested evidence. Run targeted tests once per relevant change set and rerun after later edits or hook autofixes that can affect the tested behavior. Do not rerun hook-covered checks. --> - [x] PR description includes the DCO sign-off declaration and every commit appears as `Verified` in GitHub - [x] Normal `pre-commit`, `commit-msg`, and `pre-push` hooks passed, or `npm run check:diff` passed when hooks were skipped or unavailable - [x] Targeted behavior tests pass for the current change set, or tests are marked not applicable above — command/result or justification: Tests not applicable, release-note prose only. - [ ] Applicable broad gate passed — `npm test` for broad runtime/test-harness changes; `npm run check` for repo-wide validation/coverage changes — command/result: - [x] Quality Gates section completed with required justifications or waivers - [x] No secrets, API keys, or credentials committed - [ ] `npm run docs` builds without warnings (doc changes only) - [x] Doc pages follow the [style guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md) (doc changes only) - [ ] New doc pages include SPDX header and frontmatter (new pages only) Docs validation note: `npm run docs:check-agent-variants && npm run docs:check-routes && git diff --check` passed. Full `npm run docs` is currently blocked before Fern validation because the pinned `fern-api@5.65.2` package is unavailable from npm (`ETARGET No matching version found`). --- <!-- DCO sign-off is required in this PR description, and every commit must appear as Verified in GitHub. Run: git config user.name && git config user.email --> Signed-off-by: Julie Yaunches <jyaunches@nvidia.com> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Added release notes for v0.0.79 with a new summary of recent improvements, including onboarding and inference options, operator/CLI diagnostics, sandbox recovery hardening, runtime limits, network policy behavior, and release validation updates. * Added updated references and links for the latest release. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
Summary
Add a deterministic bounded-polling primitive for read-only readiness checks and migrate representative sandbox-readiness and denied-log probes. State-mutating installer/onboard/rebuild retries remain explicit.
Closes #6347
Parent epic: #6346
Changes
Verification
npm run build:clinpm run typecheck:clinpm run lintSigned-off-by: Julie Yaunches jyaunches@nvidia.com
Summary by CodeRabbit
New Features
Bug Fixes
Tests